<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>马力机</title>
	<style>
		body { 
            margin: 0; 
            padding: 0; 
			font-family: 'Arial';
        }
        canvas { 
            display: block;
        }
		.canvas-container {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            margin: 0;
            padding: 0;
        }
		button {
			margin-right: 10px;
			font-size: 20px;
			padding: 10px 30px;
			background-color: #4CAF50;
			color: white;	
			border: none;
			border-radius: 5px;
			cursor: pointer;
		}
	</style>
</head>

<body>
	<div class="canvas-container"><div id="container"></div></div>
	<div style="position: fixed;bottom:10px;width:100vw;">
		<button id="pause" style="background-color: #f60;">暂停获取</button>
		<button id="reset" style="background-color: #666;">重置图表</button>
		<button id="save">保存配置</button>
	</div>
	<div style="position: fixed;width:340px;height:200px;right:10px;bottom:10px;">
		<textarea id="rpmZoneText" style="width:100%;height:100%;padding:10px;font-size:20px;"></textarea>
	</div>
	<script src="./konva.min.js"></script>
	<script>
		const ws = new WebSocket('ws://192.168.1.3:8080');
		var maxPower = 0; //最大功率HP
		var maxTorque = 0; //最大扭矩LBF·ft
		var maxPowerRpm = 0; //最大功率转速
		var maxTorqueRpm = 0; //最大扭矩转速
		var maxPowerLimit = 100; //最大功率限制
		var maxTorqueLimit = 100; //最大扭矩限制
		var maxPowerRpm = 0; //最大功率转速
		var maxTorqueRpm = 0; //最大扭矩转速
		var width = 1400;
		var height = 800;

		var powerData = [];
		var torqueData = [];

		// first we need to create a stage
		var stage = new Konva.Stage({
			container: 'container',   // id of container <div>
			width,
			height
		});
		var gridLayer = new Konva.Layer();
		var powerDotLayer = new Konva.Layer();
		var torqueDotLayer = new Konva.Layer();

		var engineMaxRpm = 0; //最大转速
		var engineIdleRpm = 0; //空转转速

		//绘制当前状态
		var currentText = new Konva.Layer();
		var currentPowerText = new Konva.Text({
			x: 1000,
			y: 100,
			text: '0',
			fontSize: 100,
			fontFamily: 'Arial',
			fill: '#FF0000'
		});
		var currentPowerText2 = new Konva.Text({
			x: 1000,
			y: 70,
			text: 'Max Power(HP):',
			fontSize: 20,
			fontFamily: 'Arial',
			fill: '#000000'
		});
		var currentPowerText3 = new Konva.Text({
			x: 1000,
			y: 200,
			text: 'at rpm:-',
			fontSize: 20,
			fontFamily: 'Arial',
			fill: '#000000'
		});

		var currentTorqueText = new Konva.Text({
			x: 1000,
			y: 270,
			text: '0',
			fontSize: 100,
			fontFamily: 'Arial',
			fill: '#0000FF'
		});
		var currentTorqueText2 = new Konva.Text({
			x: 1000,
			y: 240,
			text: 'Max Torque(LBF·ft):',
			fontSize: 20,
			fontFamily: 'Arial',
			fill: '#000000'
		});
		var currentTorqueText3 = new Konva.Text({
			x: 1000,
			y: 370,
			text: 'at rpm:-',
			fontSize: 20,
			fontFamily: 'Arial',
			fill: '#000000'
		});
		var currentRpmText = new Konva.Text({
			x: 1000,
			y: 460,
			text: '0',
			fontSize: 100,
			fontFamily: 'Arial',
			fill: '#000000'
		});
		var currentRpmText2 = new Konva.Text({
			x: 1000,
			y: 430,
			text: 'Current Rpm:',
			fontSize: 20,
			fontFamily: 'Arial',
			fill: '#000000'
		});
		var currentCarId = new Konva.Text({
			x: 100,
			y: 20,
			text: 'Car Id:-',
			fontSize: 60,
			fontFamily: 'Arial',
			fill: '#000000'
		});
		currentText.add(currentPowerText);
		currentText.add(currentPowerText2);
		currentText.add(currentPowerText3);
		currentText.add(currentTorqueText);
		currentText.add(currentTorqueText2);
		currentText.add(currentTorqueText3);
		currentText.add(currentRpmText);
		currentText.add(currentRpmText2);
		currentText.add(currentCarId);

		stage.add(currentText);
		stage.add(powerDotLayer);
		stage.add(torqueDotLayer);

		ws.onmessage = function(event) {
			if( isPaused ){
				return;
			}
		    const data = JSON.parse(event.data);
			if( (data.EngineMaxRpm && data.EngineMaxRpm != engineMaxRpm) || (data.EngineIdleRpm && data.EngineIdleRpm != engineIdleRpm) ){
				engineMaxRpm = data.EngineMaxRpm;
				engineIdleRpm = data.EngineIdleRpm;
				drawGrid();
			}
			let currentRpm = Math.floor(data.CurrentEngineRpm) ;
			let power = Math.floor(data.Power / 1000 * 1.34102209 ) ;
			let torque = Math.floor(data.Torque * 0.73756215 ) ;
			power = power > 0 ? power : 0;
			torque = torque > 0 ? torque : 0;

			powerData.push([currentRpm, power]);
			torqueData.push([currentRpm, torque]);
			
			if( power > maxPower ){
				maxPower = power;
				currentPowerText.setText(maxPower);
				currentPowerText3.setText('at rpm:'+ currentRpm);
			}
			if( torque > maxTorque ){
				maxTorque = torque;
				currentTorqueText.setText(maxTorque);
				currentTorqueText3.setText('at rpm:'+ currentRpm);
			}
			currentRpmText.setText(currentRpm);
			if(data.CarOrdinal)currentCarId.setText('Car Id:'+ data.CarOrdinal);

			if( power > 0 ){ //绘制功率点
				drawPoint( 'power' , currentRpm , power )
			}
			if( torque > 0 ){ //绘制扭矩点
				drawPoint( 'torque', currentRpm , torque )
			}

			if( power > maxPowerLimit ){
				maxPowerLimit = Math.ceil(power / 100) * 100;
				powerDotLayer.destroy();
				powerDotLayer = new Konva.Layer();
				stage.add(powerDotLayer);
				powerData.forEach(function(item){
					drawPoint( 'power' , item[0] , item[1] )
				});
			}

			if( torque > maxTorqueLimit ){
				maxTorqueLimit = Math.ceil(torque / 100) * 100;
				torqueDotLayer.destroy();
				torqueDotLayer = new Konva.Layer();
				stage.add(torqueDotLayer);
				torqueData.forEach(function(item){
					drawPoint( 'torque', item[0] , item[1] )
				});
			}

			powerDotLayer.draw();
			torqueDotLayer.draw();
			currentText.draw();
		};

		function drawPoint( type, rpm, value ){
			var layer = type == 'power'? powerDotLayer : torqueDotLayer;
			var maxLimit = type == 'power'? maxPowerLimit : maxTorqueLimit;
			var dot = new Konva.Circle({
				x: rpm * 800 / engineMaxRpm + 100,
				y: 700 - value * 600 / maxLimit,
				radius: 2,
				fill: type == 'power'? '#ff0000' : '#0000ff',
			});
			layer.add(dot);
		}

		//绘制网格
		function drawGrid() {
			gridLayer.clear();
			var rpm = 0;
			var step = 800 / Math.ceil(engineMaxRpm / 1000);
			var i = 0;

			//绘制X轴
			var xline = new Konva.Line({
				points: [ 100, 700, 900, 700 ],
				stroke: '#aaaaaa',
				strokeWidth: 2,
				lineCap: 'round',
				lineJoin: 'round'
			});
			gridLayer.add(xline);




			while( rpm < engineMaxRpm ){
				//绘制Y轴
				var line = new Konva.Line({
					points: [ i * step + 100 , 100, i * step + 100, 700 ],
					stroke: '#aaaaaa',
					strokeWidth: 2,
					lineCap: 'round',
					lineJoin: 'round'
				});
				gridLayer.add(line);
				//绘制rpm值
				var text = new Konva.Text({
					x: i * step + 100 - 20,
					y: 710,
					text: rpm || 'RPM',
					fontSize: 20,
					fontFamily: 'Arial',
					fill: '#aaaaaa'
				});
				gridLayer.add(text);

				rpm += 1000;
				i++;
			}
			gridLayer.draw();
		}

		stage.add(gridLayer);

		//窗口缩放
		function resizeWindow() {
            // 获取容器尺寸
			const container = document.querySelector('.canvas-container');
            const containerWidth = container.clientWidth;
            const containerHeight = container.clientHeight;
            
            // 计算缩放比例
            const scale = Math.min(
                containerWidth / width,
                containerHeight / height
            );
            document.body.style.transform = `scale(${scale})`;
        }

        // 初始调整
        resizeWindow();
        // 监听窗口变化
        window.addEventListener('resize', resizeWindow);


		//UI buttons
		var isPaused = false;
		const pauseButton = document.getElementById('pause');
		const resetButton = document.getElementById('reset');

		pauseButton.addEventListener('click', function() {
			isPaused = !isPaused;
			pauseButton.innerHTML = isPaused ? '继续' : '暂停';
		});

		resetButton.addEventListener('click', function() {
			location.reload();
		});

		//获取ini
		window.addEventListener('load', () => {
			fetch('./rpmZone.ini?'+new Date().getTime())
			.then(response => response.text())
			.then(text => {
				document.getElementById('rpmZoneText').value = text;
			})
			.catch(error => console.error(error));
		});
		//保存ini
		const saveButton = document.getElementById('save');
		saveButton.addEventListener('click', () => {
			const text = document.getElementById('rpmZoneText').value;
			//fetch('./rpmZone.ini?'+new Date().getTime(), {
			fetch('./save', {
				method: 'POST',
				headers: {
					'Content-Type': 'text/plain'
				},
				body: text
			})
			.then(response => response.text())
			.then(text => {
				alert('保存成功');
			})
			.catch(error=>alert('保存失败'));
		});
	</script>
</body>

</html>